package com.jungle.system.application.service.impl;

import com.jungle.common.utils.sql.StringUtils;
import com.jungle.common.core.page.TableDataInfo;
import com.jungle.common.core.domain.PageQuery;
import com.jungle.pojo.domain.vo.SysOssResult;
import com.jungle.system.application.domain.bo.SysOssBo;
import com.jungle.system.application.repository.SysOssRepository;
import com.jungle.system.application.service.ISysOssService;
import com.jungle.system.domain.SysOss;
import com.jungle.system.utils.oss.FileImportUtil;
import com.jungle.system.utils.oss.MinioUploadUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.jungle.domain.vo.SysOssVo;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * OSS对象存储对象Service业务层处理
 *
 * @author jungle
 * @date 2023-10-03
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class SysOssServiceImpl implements ISysOssService {

    private final SysOssRepository repository;
    private final FileImportUtil fileImportUtil;
    private final MinioUploadUtil minioUploadUtil;

    @Override
    public SysOssResult upload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String url = minioUploadUtil.upload(file);
        SysOss sysOss = new SysOss();
        sysOss.setOssId(System.currentTimeMillis());
        sysOss.setUrl(url);
        sysOss.setFileSuffix(suffix);
        sysOss.setOriginalName(originalFilename);//原始文件名
        sysOss.setFileName(url.substring(url.lastIndexOf("/")+1));//生成的UUID名
        sysOss.setService("minio");
        repository.saveAndFlush(sysOss);
        return SysOssResult.builder()
                .url(url)
                .ossId(sysOss.getOssId())
                .fileName(originalFilename)
                .build();
    }

    @Override
    public SysOssResult uploadFile(MultipartFile file) throws Exception {

        byte[] fileBytes = file.getBytes();
        String path = fileImportUtil.uploadFile(fileBytes, file.getOriginalFilename());
        log.info("上传路径：{}", path);
        SysOss sysOss = new SysOss();
        sysOss.setUrl(path);
//        sysOss.setFileSuffix();
        return null;
    }

    /**
     * 查询OSS对象存储对象
     */
    @Override
    public SysOssVo queryById(Long ossId){
        return repository.findById(ossId).map(v -> com.jungle.common.utils.BeanCopyUtils.copy(v, SysOssVo.class)).orElse(null);
    }

    /**
     * 查询OSS对象存储对象列表
     */
    @Override
    public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
        Page<SysOss> result = repository.findAll(getSpecification(bo), pageQuery.pageable());
        return TableDataInfo.build(result, SysOssVo.class);
    }

    /**
     * 查询OSS对象存储对象列表
     */
    @Override
    public List<SysOssVo> queryList(SysOssBo bo) {
        return repository.findAll(getSpecification(bo)).stream()
            .map(v -> com.jungle.common.utils.BeanCopyUtils.copy(v, SysOssVo.class))
            .collect(Collectors.toList());
    }

    private Specification<SysOss> getSpecification(SysOssBo bo) {
        return (root, query, cb) -> {
            Map<String, Object> params = bo.getParams();
            List<Predicate> predicates = new ArrayList<>();
            if (bo.getOssId() != null) {
                    predicates.add(cb.equal(root.get("ossId"), bo.getOssId()));
            }
            if (StringUtils.isNotBlank(bo.getFileName())) {
                    predicates.add(cb.like(root.get("fileName"), "%" + bo.getFileName() + "%"));
            }
            if (StringUtils.isNotBlank(bo.getFileSuffix())) {
                    predicates.add(cb.equal(root.get("fileSuffix"), bo.getFileSuffix()));
            }
            if (StringUtils.isNotBlank(bo.getOriginalName())) {
                    predicates.add(cb.like(root.get("originalName"), "%" + bo.getOriginalName() + "%"));
            }
            if (StringUtils.isNotBlank(bo.getService())) {
                    predicates.add(cb.equal(root.get("service"), bo.getService()));
            }
            if (StringUtils.isNotBlank(bo.getUrl())) {
                    predicates.add(cb.equal(root.get("url"), bo.getUrl()));
            }
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        };
    }

    /**
     * 新增OSS对象存储对象
     */
    @Override
    public Boolean insertByBo(SysOssBo bo) {
        SysOss add = com.jungle.common.utils.BeanCopyUtils.copy(bo, SysOss.class);
        validEntityBeforeSave(add);
        repository.saveAndFlush(add);
        bo.setOssId(add.getOssId());
        return true;
    }

    /**
     * 修改OSS对象存储对象
     */
    @Override
    public Boolean updateByBo(SysOssBo bo) {
        SysOss update = com.jungle.common.utils.BeanCopyUtils.copy(bo, SysOss.class);
        validEntityBeforeSave(update);
        return repository.save(update) != null;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysOss entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除OSS对象存储对象
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
//        repository.deleteAllById(ids);
        return true;
    }

}
